package com.xb.loan.util.binaryConvert.parse.obj;


import com.xb.loan.util.binaryConvert.ConvertUtil;
import com.xb.loan.util.binaryConvert.config.ParseConfig;
import com.xb.loan.util.binaryConvert.config.ParseConfigManager;
import com.xb.loan.util.binaryConvert.exception.ParseException;
import com.xb.loan.util.binaryConvert.parse.ParseAble;
import com.xb.loan.util.binaryConvert.parse.ParsePointer;

import java.util.LinkedList;
import java.util.List;


public class ObjParser implements ParseAble<Object> {

	@SuppressWarnings("unchecked")
	@Override
	public Object convert(byte[] b, ParsePointer pointer, Class<?> clazz,
						  ParseConfig config) {

		Object obj = null;

		try {

			byte isNull = b[pointer.getPointer()];
			// 后移一个
			pointer.move(1);

			if (isNull == 0) {

				return null;
			}
			
			obj = clazz.getConstructor().newInstance();

			ParseConfig[] configChain = ParseConfigManager.getConfigChain(obj
					.getClass());

			for (int i = 0; i < configChain.length; i++) {

				ParseConfig parseConfig = configChain[i];
				// 获取解析类
				ParseAble<Object> parser = ParseConfigManager.getParser(parseConfig.getParseType());
				// 设置转换属性
				parseConfig.set(obj,parser.convert(b, pointer, parseConfig.getFieldType(), parseConfig));
			}

		} catch (Exception e) {

			throw new ParseException("ObjParser convert " + obj + " error.", e);
		}

		return obj;
	}

	@SuppressWarnings("unchecked")
	@Override
	public byte[] format(Object obj, ParseConfig config) throws ParseException {

		if (obj == null) {

			return new byte[] { 0 };
		}

		ParseConfig[] configChain = ParseConfigManager.getConfigChain(obj
				.getClass());

		List<byte[]> fieldBytes = new LinkedList<byte[]>();

		int sizes = 1;
		// 加入对象标识位
		fieldBytes.add(0, new byte[]{1});

		for (int i = 0; i < configChain.length; i++) {

			ParseConfig parseConfig = configChain[i];
			// 获取解析类
			ParseAble<Object> parser = ParseConfigManager.getParser(parseConfig.getParseType());

			byte[] bb = null;

			try {
				bb = parser.format(parseConfig.get(obj),
						parseConfig);
			} catch (Exception e) {

				throw new ParseException("ObjParser parse " + obj + " error.",
						e);
			}

			sizes += bb.length;

			fieldBytes.add(bb);

		}

		return ConvertUtil.combatAll(fieldBytes, sizes);
	}

}
